import socket
import threading
import time

def test_single_client(host='127.0.0.1', port=12345):
    """测试单客户端连接和消息回复"""
    try:
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.settimeout(3)
            s.connect((host, port))
            
            # 发送测试消息
            test_message = "Hello, Server! (Single Client)"
            s.sendall(test_message.encode())
            print(f"Sent to server: {test_message}")
            
            # 接收回复
            response = s.recv(1024).decode()
            print(f"Received from server: {response}")
            
            # 验证回声是否正确
            if response == test_message:
                print("✅ Single client test PASSED")
            else:
                print(f"❌ Single client test FAILED. Expected: {test_message}, Got: {response}")
    
    except Exception as e:
        print(f"❌ Single client test FAILED with error: {e}")

def test_multiple_clients(host='127.0.0.1', port=12345, num_clients=3):
    """测试多个客户端同时连接和消息回复"""
    results = []
    lock = threading.Lock()
    threads = []
    
    def client_thread(client_id):
        try:
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                s.settimeout(3)
                s.connect((host, port))
                
                # 发送唯一消息
                test_message = f"Hello from Client {client_id}"
                s.sendall(test_message.encode())
                
                # 接收回复
                response = s.recv(1024).decode()
                
                # 验证回声是否正确
                success = (response == test_message)
                with lock:
                    results.append(success)
                    print(f"Client {client_id}: {'✅' if success else '❌'} Echo match")
        except Exception as e:
            with lock:
                results.append(False)
                print(f"Client {client_id} failed: {e}")
    
    # 创建并启动多个客户端线程
    for i in range(num_clients):
        t = threading.Thread(target=client_thread, args=(i,))
        threads.append(t)
        t.start()
    
    # 等待所有线程完成
    for t in threads:
        t.join()
    
    # 检查所有结果
    if len(results) == num_clients and all(results):
        print("✅ Multiple clients test PASSED")
    else:
        print(f"❌ Multiple clients test FAILED. Passed: {sum(results)}/{num_clients}")

def test_client_timeout(host='127.0.0.1', port=12345, timeout=5):
    """测试服务器超时关闭连接"""
    try:
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.connect((host, port))
            print("⌛️ Connected to server, waiting for timeout...")
            
            start_time = time.time()
            
            # 等待时间超过服务器超时设置
            while time.time() - start_time < timeout * 1.5:
                try:
                    # 尝试接收数据（应该超时）
                    s.settimeout(1)
                    data = s.recv(1024)
                    if not data:
                        break
                except socket.timeout:
                    continue
            
            # 测试连接是否已关闭
            try:
                s.sendall(b"Ping")
                response = s.recv(1024)
                if not response:
                    print("✅ Timeout test PASSED: Server closed connection as expected")
                else:
                    print("❌ Timeout test FAILED: Server did not close connection response: "+ response)
            except Exception as e:
                print("✅ Timeout test PASSED: Server closed connection")
    
    except Exception as e:
        print(f"❌ Timeout test FAILED with error: {e}")

if __name__ == "__main__":
    server_host = 'localhost'  # 服务器地址
    server_port = 8080         # 服务器端口
    timeout_seconds = 15         # 超时时间（需要与服务器设置匹配）
    
    print("Starting TCP echo server tests...")
    print("="*50)
    
    # 测试单客户端
    print("Running single client test...")
    test_single_client(server_host, server_port)
    print("-"*50)
    
    # 测试多客户端
    print("Running multiple clients test...")
    test_multiple_clients(server_host, server_port, num_clients=3)
    print("-"*50)
    
    # 测试超时
    print("Running connection timeout test...")
    test_client_timeout(server_host, server_port, timeout=timeout_seconds)
    print("="*50)
    
    print("All tests completed")